package com.cybertron.ironhide.spider.plugin;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.cybertron.ironhide.spider.SpiderListener;
import com.cybertron.ironhide.spider.xml.Plugin;

/**
 * 插件管理
 * 
 * @author weiwei l.weiwei@163.com
 * @date 2013-1-15 下午03:00:57
 */
public class PluginManager {

	private Map<String, Plugin> impls = new HashMap<String, Plugin>();

	/**
	 * 加载配置文件。很重要
	 * 
	 * @date 2013-1-2 下午07:13:49
	 * @param plugins
	 * @param listener
	 * @throws Exception
	 */
	public void loadPluginConf(Collection<Plugin> plugins,
			SpiderListener listener) throws Exception {
		if (plugins == null || plugins.isEmpty())
			listener.onInfo(Thread.currentThread(), null,
					"there is no plugins to load");

		for (Plugin plugin : plugins) {
			listener.onInfo(Thread.currentThread(), null, "plugin info -> \n"
					+ plugin);
			String point = plugin.getPoint();

			if (!ExtensionPoints.contains(point)) {
				String err = "plugin["
						+ plugin.getValue()
						+ "] extension-point["
						+ point
						+ "] not found please confim the point value must be in "
						+ ExtensionPoints.string();
				Exception e = new Exception(err);
				listener.onError(Thread.currentThread(), null, err, e);
				throw e;
			}
			this.impls.put(point, plugin);
			listener.onInfo(Thread.currentThread(), null,
					"plugin[" + plugin.getValue() + "] extension-point["
							+ point + "] loading ok ");
		}

	}

	/**
	 * 获取扩展点的所有实现类
	 * 
	 * @date 2013-1-2 下午07:14:14
	 * @param <T>
	 * @param name
	 * @return
	 */
	public <T> ExtensionPoint<T> getExtensionPoint(final String pointName) {
		if (!this.impls.containsKey(pointName))
			return null;

		final Plugin plugin = this.impls.get(pointName);
		return new ExtensionPoint<T>() {
			@SuppressWarnings("unchecked")
			@Override
			public T getExtension() {
				T t = null;
				String value = plugin.getValue();
				try {
					Class<T> cls = (Class<T>) Thread.currentThread()
							.getContextClassLoader().loadClass(value);
					t = cls.newInstance();
				} catch (ClassNotFoundException e) {
					throw new RuntimeException("plugin class -> " + value
							+ " of ExtensionPoint[" + pointName
							+ "] not found !", e);
				} catch (InstantiationException e) {
					throw new RuntimeException("plugin class -> " + value
							+ " of ExtensionPoint[" + pointName
							+ "] instaniation fail !", e);
				} catch (IllegalAccessException e) {
					throw new RuntimeException("plugin class -> " + value
							+ " of ExtensionPoint[" + pointName
							+ "] illegal access !", e);
				}
				return t;
			}

		};
	}
}
